package com.boot2.core.web;

import com.boot2.core.conf.CorsConf;
import com.boot2.core.conf.CorsRegistrationConfig;
import com.boot2.core.utils.StringUtils;
import com.boot2.core.web.filter.SysFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.config.annotation.CorsRegistration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author zhangweilin
 * @ClassName: AbstractMvcConfig
 * @description: 抽象mvc配置
 * @date 2017年12月19日 下午4:24:49
 */
// 继承WebMvcConfigurerAdapter类，重写其方法可对Spring MVC进行配置
//public abstract class AbstractMvcConfig implements WebMvcConfigurer {
public abstract class AbstractMvcConfig extends WebMvcConfigurationSupport {
//public abstract class AbstractMvcConfig extends WebMvcConfigurerAdapter {

//    @Autowired
//    XssHttpServletFilter xssHttpServletFilter;

    @Autowired
    SysInterceptor sysInterceptor;

    @Autowired
    RequestMappingHandlerAdapter requestMappingHandlerAdapter;

    @Resource(name = "fastJsonHttpMessageConverter")
    HttpMessageConverter httpMessageConverter;

    @Resource(name = "stringHttpMessageConverter")
    HttpMessageConverter stringHttpMessageConverter;

    @Autowired
    protected CorsConf corsConf;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 借用此处，配置requestMappingHandlerAdapter (属性配置文件中无效，spring boot有bug)
        requestMappingHandlerAdapter.setIgnoreDefaultModelOnRedirect(true);
        registry.addInterceptor(sysInterceptor).addPathPatterns("/**"); // 系统级拦截，匹配全部
        super.addInterceptors(registry);
    }


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        super.addResourceHandlers(registry);
        //  addResourceHandler指的是对外暴露的访问路径,addResourceLocations指的是文件放置的目录
        // swagger采用了webjars当界面。故需要过滤掉
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/res/**").addResourceLocations("classpath:/res/");
        registry.addResourceHandler("/cacheMonitor/**").addResourceLocations("classpath:/templates/redis/monitor/");
    }

    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        // viewResolver.setPrefix("/WEB-INF/classes/views/");
        viewResolver.setPrefix("/WEB-INF/classes/jsp/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // super.configurePathMatch(configurer);
        configurer.setUseSuffixPatternMatch(false);
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // TODO Auto-generated method stub
//        System.out.println("前converters = " + converters);
        super.configureMessageConverters(converters);
        converters.add(stringHttpMessageConverter);
        converters.add(httpMessageConverter);
//        System.out.println("后converters = " + converters);
    }

    @Bean
    public FilterRegistrationBean<SysFilter> sysFilter() {
        FilterRegistrationBean<SysFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        SysFilter sysFilter = new SysFilter();
        filterRegistrationBean.setFilter(sysFilter);
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setOrder(Integer.MIN_VALUE);
        filterRegistrationBean.setName("sysFilter");
        return filterRegistrationBean;
    }

    /**
     * 跨域过滤器,有效，即，当同源时，不会出现相应的header,而跨源时，才会显示与之相配的header
     * @return
     */
//    @Bean
//    public CorsFilter corsFilter() {
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        CorsConfiguration config = new CorsConfiguration();
//        config.setAllowCredentials(true);
//        config.addAllowedOrigin("http://www.w3school.com.cn");
//        config.addAllowedHeader("*");
//        config.addAllowedMethod("*");
//        source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效
//        return new CorsFilter(source);
//    }

    /**
     *跨域过滤器,有效，即，当同源时，不会出现相应的header,而跨源时，才会显示与之相配的header
     */
//    @Bean
//    public FilterRegistrationBean corsFilter() {
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        CorsConfiguration config = new CorsConfiguration();
//        config.setAllowCredentials(true);
//        config.addAllowedOrigin("http://localhost:9000");
//        config.addAllowedHeader("*");
//        config.addAllowedMethod("*");
//        source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效
//        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
//        bean.setOrder(1);
//        return bean;
//    }

    /**
     * 跨域解决,参考CorsConf中，在spring boot配置文件中，以cors为前缀各自配置即可,
     * 当同源时，响应中不会出现相应的header,而跨源时，才会显示与之相配的header
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        Map<String, CorsRegistrationConfig> configMap = corsConf.getConfig();
        if (!CollectionUtils.isEmpty(configMap)) {
            Iterator<String> keys = configMap.keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next();
                CorsRegistrationConfig item = configMap.get(key);
                CorsRegistration corsRegistration = null;
                if (StringUtils.isNotEmpty(item.getMapping())) {
                    corsRegistration = registry.addMapping(item.getMapping());
                } else {
                    corsRegistration = registry.addMapping("/**");
                }
                if (item.getAllowCredentials() != null) {
                    corsRegistration.allowCredentials(item.getAllowCredentials());
                }
                if (StringUtils.isNotEmpty(item.getAllowedOrigins())) {
                    String[] allowedOriginArray = item.getAllowedOrigins().split(",");
                    corsRegistration.allowedOrigins(allowedOriginArray);
                }
                if (StringUtils.isNotEmpty(item.getAllowedMethods())) {
                    String[] allowedMethodArray = item.getAllowedMethods().split(",");
                    corsRegistration.allowedMethods(allowedMethodArray);
                }
                if (StringUtils.isNotEmpty(item.getAllowedHeaders())) {
                    String[] allowedHeaderArray = item.getAllowedHeaders().split(",");
                    corsRegistration.allowedHeaders(allowedHeaderArray);
                }
                if (StringUtils.isNotEmpty(item.getExposedHeaders())) {
                    String[] exposedHeaders = item.getExposedHeaders().split(",");
                    corsRegistration.exposedHeaders(exposedHeaders);
                }
            }
        }
    }

//    /**
//     * 跨域解决,参考CorsConf中，在spring boot配置文件中，以cors为前缀各自配置即可
//     * @param registry
//     */
//    @Override
//    public void addCorsMappings(CorsRegistry registry) {
//        CorsRegistration corsRegistration = null;
//        if (StringUtils.isNotEmpty(corsConf.getMapping())) {
//            corsRegistration= registry.addMapping(corsConf.getMapping());
//        } else {
//            corsRegistration=registry.addMapping("/**");
//        }
//        if (StringUtils.isNotEmpty(corsConf.getAllowedHeaders())) {
//            corsRegistration.allowedHeaders(corsConf.getAllowedHeaders());
//        }
//        if (StringUtils.isNotEmpty(corsConf.getExposedHeaders())) {
//            corsRegistration.exposedHeaders(corsConf.getExposedHeaders());
//        }
//        if (StringUtils.isNotEmpty(corsConf.getAllowedMethods())) {
//            corsRegistration.allowedMethods(corsConf.getAllowedMethods());
//        }
//        if (StringUtils.isNotEmpty(corsConf.getAllowedOrigins())) {
//            corsRegistration.allowedOrigins(corsConf.getAllowedOrigins());
//        }
//        if (null!=corsConf.getAllowCredentials()) {
//            corsRegistration.allowCredentials(corsConf.getAllowCredentials());
//        }
//        if (null!=corsConf.getMaxAge()) {
//            corsRegistration.maxAge(corsConf.getMaxAge());
//        }
//    }

    /**
     * 配置过滤器
     *
     * @return
     */
//    @Bean
//    @Order(1)
//    public FilterRegistrationBean someFilterRegistration() {
//        FilterRegistrationBean registration = new FilterRegistrationBean();
//        xssHttpServletFilter.setExclude("/static/*;/robots.txt;");
//        registration.setFilter(xssHttpServletFilter);
//        // registration.addUrlPatterns("/*");
//        registration.setName("xssFilter");
//        return registration;
//    }
}